using System;
using System.Reflection;
using Autofac;
using Autofac.Extensions.DependencyInjection;
using Autofac.Extras.DynamicProxy;
using ESoft.Core.Initialize;
using ESoft.Core.Interceptor;
using ESoft.Core.Logging;
using ESoft.Core.Logging.Log4Net;
using ESoft.Core.Model;
using ESoft.Core.Web.Common.Filters;
using ESoft.Core.Web.Config;
using ESoft.Portal.Areas.ContentManager.Data.Service;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Net.Http.Headers;

namespace ESoft.Portal
{
    public class Startup
    {
        public IConfiguration Configuration { get; }

        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            services.AddMemoryCache();
            services.AddCors();
            services.AddDbContext<DataContext>(options => options.UseMySql(this.Configuration.GetConnectionString("ConnectionStrings")));
            services.AddMvc(options =>
            {
                options.Filters.Add<HttpGlobalExceptionFilter>();
                options.Filters.Add<UserAuthorizeAttribute>();
            }).AddJsonOptions(json =>
            {
                json.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
            });

            services.AddAuthentication(WebParameter.UserAuthenticationScheme)
                .AddCookie(WebParameter.UserAuthenticationScheme, options =>
                {
                    options.LoginPath = "/Login/Index";
                });

            IContainer applicationContainer = BuildServiceContainer(services);
            return applicationContainer.Resolve<IServiceProvider>();
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            app.UseCors(builder => builder
                .AllowAnyOrigin()
                .AllowAnyMethod()
                .AllowAnyHeader()
                .AllowCredentials());

            app.UseStaticFiles(new StaticFileOptions
            {
                OnPrepareResponse = ctx =>
                {
                    const int durationInSeconds = 60 * 60 * 24;
                    ctx.Context.Response.Headers[HeaderNames.CacheControl] =
                        "public,max-age=" + durationInSeconds;
                }
            });
            app.UseAuthentication();
            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{channelId?}");

                routes.MapRoute(
                   name: "article",
                   template: "{controller=Article}/{action=Detail}/{articleId?}");

                routes.MapRoute(
                    name: "areas",
                    template: "{area:exists}/{controller=Home}/{action=Index}/{id?}"
                );
            });
            Log4NetLoggerAdapter adapter = new Log4NetLoggerAdapter();
            LogManager.AddLoggerAdapter(adapter);
            DatabaseInitializer.AddMapperAssembly(LoadAutofaceAssembles());
            DatabaseInitializer.Initialize();
          
        }

        private static IContainer BuildServiceContainer(IServiceCollection services)
        {
            var builder = new ContainerBuilder();
            builder.RegisterType<TransactionInterceptor>().InstancePerLifetimeScope();
            Assembly[] assemblyArr = LoadAutofaceAssembles();

            builder.RegisterAssemblyTypes(assemblyArr).Where(t => t.Name.EndsWith("DAO", StringComparison.OrdinalIgnoreCase)).AsImplementedInterfaces().EnableInterfaceInterceptors().InterceptedBy(typeof(TransactionInterceptor)).InstancePerLifetimeScope();

            builder.RegisterAssemblyTypes(assemblyArr)
                .Where(t => t.Name.EndsWith("Service", StringComparison.OrdinalIgnoreCase)).AsImplementedInterfaces()
                .EnableInterfaceInterceptors().InterceptedBy(typeof(TransactionInterceptor)).InstancePerLifetimeScope();

            builder.Populate(services);
            var applicationContainer = builder.Build();
            return applicationContainer;
        }

        private static Assembly[] LoadAutofaceAssembles()
        {
            return new Assembly[] {
                Assembly.Load("ESoft.Core"),
                Assembly.Load("ESoft.Portal")
            };
        }
    }
}
